package {

    import flash.display.*;
    import flash.events.*;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.system.Capabilities;
    import flash.text.*;
    import flash.utils.*;
    
    import mx.core.BitmapAsset;
    import mx.events.*;
    import mx.preloaders.*;

    public class Preloader extends DownloadProgressBar {
		[Embed(source="../../../resources/numberset.png")]
        private var numbersetClass:Class;      

		
		private var DEBUG:Boolean = false; // true == label with environment settings will be shown

				
		private var data:Array; // contains single tiles as BitmapData instances

		private var digit0:Sprite;
		private var digit1:Sprite;
		private var percent:Sprite;

		private const NR_SHAPES:int = 12;
		private const IDX_PERCENT_SIGN:int = 11; 
		private const SHAPE_HEIGHT:int = 38;
		private const SHAPE_WIDTH:int = 31;
		private const SHAPE_SPACING:int = 3;
		private const SHAPE_POINT:Point = new Point(0,0);
		private const MAX_INCREMENT:int = 2;

    	private const BG_COLOR:uint = 0xffffff; //0x383838; //0xc0c0c0; 
        
		private var actValue:uint = 0;
		private var destValue:uint = 0;
		private var finish:Boolean = false;

    
        public function Preloader() {    
            super();
            addEventListener(Event.ADDED_TO_STAGE,init);
        }
        
        private function generateTiles(): void {
			var i:int;
			
			if (data == null) {
				data = new Array(NR_SHAPES);
	        	var orig:BitmapAsset = new numbersetClass() as BitmapAsset;
				var bm:BitmapData = orig.bitmapData;

				var sourceRect:Rectangle = new Rectangle(0,0,SHAPE_WIDTH,SHAPE_HEIGHT);

				for (i=0;i<NR_SHAPES;i++) {
					var tile:BitmapData = new BitmapData(SHAPE_WIDTH,SHAPE_HEIGHT,false);
					sourceRect.x = 0;
					sourceRect.y = i*SHAPE_HEIGHT;
					sourceRect.width = SHAPE_WIDTH;
					sourceRect.height = SHAPE_HEIGHT;
					tile.copyPixels(bm,sourceRect,SHAPE_POINT);
					data[i] = tile;
				}
				
				bm.dispose();
				orig.bitmapData = null;								
			}
        }
        
        private function updateSprite(sprite:Sprite, shapeIdx:uint): void {
        	with (sprite.graphics) {
        		clear();
				beginBitmapFill(data[shapeIdx] as BitmapData);
				drawRect(0,0,SHAPE_WIDTH,SHAPE_HEIGHT);
				endFill();        		
        	}
        }

		private function initSprite(spriteIdx:uint):Sprite {
			var sprite:Sprite = new Sprite();
			sprite.x = -1000;
			sprite.y = -1000;
			updateSprite(sprite,spriteIdx);
			addChild(sprite);
			return sprite;
		}


		private function generateDebugInfo(showLabel:Boolean):void {
			var infotext:String = "";
			try {
				var buildtime:String = String(LoaderInfo(this.root.loaderInfo).parameters["buildtime"]);
				infotext += buildtime+" ";
			}            
			catch(e:Error) {				
			}                        
			infotext += "(player: "+ Capabilities.version;
			infotext += (Capabilities.isDebugger) ? "/dbg" : "/std";
			infotext += " hosted by: "+Capabilities.os+")";

			if (showLabel) {
            	var lbl:TextField = new TextField();
            	lbl.autoSize = TextFieldAutoSize.LEFT;
            	lbl.background = false;
            	lbl.border = false;			
            	var format:TextFormat = new TextFormat();
            	format.font = "Verdana";
            	format.color = 0x606060;
            	format.size = 10;

	            lbl.defaultTextFormat = format;
    	        lbl.text = infotext;
        	    addChild(lbl);
   			}            
            trace("[environment] buildtime="+infotext);
		}

                        
        private function init(e:Event):void {		
			removeEventListener(Event.ADDED_TO_STAGE,init);

			generateDebugInfo(DEBUG);									 

			generateTiles();
			digit0  = initSprite(0);
			digit1  = initSprite(0);
			percent = initSprite(IDX_PERCENT_SIGN);
			addEventListener(Event.ENTER_FRAME, enterFrame);			
        }


		private function enterFrame(e:Event):void {
			if (actValue != destValue) {
				var increment:Number = (destValue - actValue)/2.0;
				if (increment>MAX_INCREMENT) increment = MAX_INCREMENT;
				else if (increment<1) 		 increment = 1;
				
				var number:Number = actValue + increment;
				if (number > destValue) number = destValue;
				
				var result:uint = uint(number);
				if (result != actValue) {
					handlePercent(result);
					actValue = result;
				}
			}
			else {
				if (finish) {
					dispatchEvent(new Event(Event.COMPLETE));
					cleanup();
				}
			}
		}

        // Define the event listeners for the preloader events.
        override public function set preloader(preloader:Sprite):void {
            preloader.addEventListener(ProgressEvent.PROGRESS, handleProgress);    
            preloader.addEventListener(FlexEvent.INIT_COMPLETE, handlePreloadingDone);
            preloader.addEventListener(Event.RESIZE, resizeHandler);
        }
                                    
        private function resizeHandler(): void {                    
        	with(graphics) {
            	clear();
            	beginFill(BG_COLOR);
            	drawRect(0,0,stageWidth,stageHeight);
         	}
            
			digit0.x = (stage.stageWidth -SHAPE_WIDTH)/2;
			digit0.y = (stage.stageHeight-SHAPE_HEIGHT)/2;
			digit1.x = digit0.x - (SHAPE_WIDTH+SHAPE_SPACING);
			digit1.y = digit0.y;
			percent.x = digit0.x + (SHAPE_WIDTH+SHAPE_SPACING);
			percent.y = digit0.y;                              
        }
        
        private function handleProgress(event:ProgressEvent):void {
            resizeHandler();
            var percent: uint = event.bytesLoaded * 100 / event.bytesTotal;
            
            if (percent>99) percent = 99;
            destValue = percent;
            //destValue = handlePercent(percent);//txt.text = percent + "%";
        }
            
        private function handlePercent(percent:uint):void {
        	//if (percent > 99) percent = 99; // clip to 99 (2-digits!)

			updateSprite(digit0,percent%10);
			updateSprite(digit1,(percent/10)%10);
        }
        
           
        private function handlePreloadingDone(event:Event):void {
			var preloader:Sprite = event.target as Sprite;

            preloader.removeEventListener(ProgressEvent.PROGRESS, handleProgress);    
            preloader.removeEventListener(FlexEvent.INIT_COMPLETE, handlePreloadingDone);
            preloader.removeEventListener(Event.RESIZE, resizeHandler);

			finish = true;
        }

		private function cleanup():void {
			removeEventListener(Event.ENTER_FRAME, enterFrame);	
			removeChild(digit0);
			removeChild(digit1);
			removeChild(percent);
			for (var i:int=0;i<data.length;i++) {
				(data[i] as BitmapData).dispose();
				data[i] = null;
			}
			digit0=digit1=percent=null;
  		}
  		  
        private function dispatchComplete():void {			
			dispatchEvent(new Event(Event.COMPLETE));
			cleanup();
        }
    }
}